package com.zn.net
{
    import com.zn.log.Log;
    
    import flash.events.AsyncErrorEvent;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.NetStatusEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.NetConnection;

    [Event(name="ioError", type="flash.events.IOErrorEvent")]
    [Event(name="success", type="com.zn.net.NetConn")]
    [Event(name="closed", type="com.zn.net.NetConn")]
    [Event(name="failed", type="com.zn.net.NetConn")]
    public class NetConn extends EventDispatcher
    {
        public static const SUCCESS:String = "success";

        public static const CLOSED:String = "closed";

        public static const FAILED:String = "failed";

        private var _netConnection:NetConnection;

        private var _url:String;

        protected var _needConned:Boolean = true;

        public function NetConn(url:String = null)
        {
            super();

            _url = url;

            _netConnection = new NetConnection();
            _netConnection.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            _netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
            _netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			_netConnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
        }
		
		protected function asyncErrorHandler(event:AsyncErrorEvent):void
		{
			Log.error(NetConn, "asyncErrorHandler", "在异步引发异常（即来自本机异步代码）时调度" + event);		
			dispatchEvent(event);
		}
		
        protected function ioErrorHandler(event:IOErrorEvent):void
        {
            Log.error(NetConn, "ioErrorHandler", "连接错误" + event);
            dispatchEvent(event);
        }

        protected function netStatusHandler(event:NetStatusEvent):void
        {
            var code:String = event.info.code;

            switch (code)
            {
                case "NetConnection.Connect.Success":
                {
                    Log.debug(NetConn, "netStatusHandler", "连接成功:" + _netConnection.uri);
                    dispatchEvent(new Event(NetConn.SUCCESS));
                    break;
                }
                case "NetConnection.Connect.Closed":
                {
                    Log.debug(NetConn, "netStatusHandler", "连接关闭");
                    dispatchEvent(new Event(NetConn.CLOSED));
                    break;
                }
                case "NetConnection.Connect.Failed":
                {
                    Log.debug(NetConn, "netStatusHandler", "连接失败");
                    dispatchEvent(new Event(NetConn.FAILED));
                    break;
                }
            }
        }

        protected function securityErrorHandler(event:SecurityErrorEvent):void
        {
            Log.error(NetConn, "securityErrorHandler", "安全错误" + event);
            dispatchEvent(event);
        }

        public function close():void
        {
            if (_netConnection.connected)
                _netConnection.close();
        }

        /**
         * 调用远程方法
         * @param method	方法名
         * @param resultFunction 成功的回调方法
         * @param failedFunction 失败的回调方法
         * @param parms 参数
         *
         */
        public function call(method:String, resultFunction:Function = null, failedFunction:Function = null, ... parms):void
        {
            if (_needConned && !_netConnection.connected)
            {
                Log.debug(NetConn, "call", "未建立服务器连接，不能调用：" + method);
                return;
            }

            var responder:Responder = new Responder(method, resultFunction, failedFunction);

            parms.unshift(method, responder);
            _netConnection.call.apply(_netConnection, parms);

        }

        public function set client(value:*):void
        {
            _netConnection.client = value;
        }

        public function connect(url:String = "", ... parms):void
        {
            if (url == "" || url == null)
            {
                if (_url == "" || _url == null)
                {
                    Log.debug(NetConn, "connect", "NetConnection 无效连接地址");
                    return;
                }
                else
                    url = _url;
            }
            parms.unshift(url);
            _netConnection.connect.apply(this, parms);
        }
		
		public function get connected():Boolean
		{
			return _netConnection.connected;
		}
    }
}